package com.trsvax.tapestry.instrumentation.services;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ComponentSource;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.RequestFilter;
import org.apache.tapestry5.services.RequestGlobals;
import org.apache.tapestry5.services.RequestHandler;
import org.apache.tapestry5.services.Response;

import com.trsvax.tapestry.instrumentation.ThreadDetail;

/*
 * log4j.appender.Tap= com.trsvax.gwthello.services.TapestryAppender
 */

public class TapestryAppender extends AppenderSkeleton implements RequestFilter {
	private static HashMap<String, ThreadDetail> logs = new HashMap<String, ThreadDetail>();
	private ThreadDetail[] loglist = new ThreadDetail[100];
	private Integer threadID = 0;

	@Inject
	private RequestGlobals requestGlobals;

	@Inject
	private ComponentSource componentSource;

	@Override
	protected void append(LoggingEvent event) {
		String name = Thread.currentThread().getName();
		if (logs.containsKey(name))
			logs.get(name).addLog(event);

	}

	@Override
	public void close() {
	}

	@Override
	public boolean requiresLayout() {
		return false;
	}

	public boolean service(Request request, Response response, RequestHandler handler) throws IOException {
		ThreadDetail details = new ThreadDetail();
		logs.put(Thread.currentThread().getName(), details);
		synchronized (threadID) {
			details.setThreadID(threadID);
			loglist[threadID++ % 100] = details;

		}
		details.setRequest(requestGlobals.getHTTPServletRequest());
		try {
			return handler.service(request, response);
		} finally {
			details.setEndTime(new Date().getTime());
			details.setUrl(requestGlobals.getHTTPServletRequest().getRequestURI().toString());
			details.setPageName(requestGlobals.getActivePageName());
			details.setPageClass(componentSource.getPage(requestGlobals.getActivePageName()).getClass());
		}
	}

	public ThreadDetail getDetail() {
		return logs.get(Thread.currentThread().getName());
	}

	public ThreadDetail[] getLogs() {
		return loglist;
	}

	public ThreadDetail getDetail(Integer id) {
		for (ThreadDetail detail : loglist) {
			if (detail.getThreadID().equals(id))
				return detail;
		}
		return null;
	}

}
